在前面两篇文章中,我们分别介绍了 Polyfill 和 Babel,那么本篇文章,我们就将两者结合起来,介绍下 Babel 中 polyfill 的解决方案。在上一篇文章中,我们简单介绍了 babel 转义的过程,先将源码解析为抽象语法树 AST,然后根据配置使用不同的插件对 AST 进行转换,然后再将转换后的 AST 输出为可编译的代码。
Babel 默认在编译时只会转换新的 JavaScript 语法(syntax),但不会转换 API,比如 Set、Maps、Generator、Proxy、Promise 等全局对象,以及一些定义在全局对象上的方法(比如Array.from、Object.assign)都不会被转译。
# @babel/polyfill
关于 babel 转换 API 这个问题,Babel 官方的一个解决方案是推出 @babel/polyfill 库。其核心依赖是 core-js@2 和 regenerater-runtime/runtime。core-js 是 JS 标准库的 polyfill,为其提供垫片能力,regenerater-runtime/runtime 用来转译 generators 和 async 函数。
下面我们分别来介绍一下 core-js 和 regenerator-runtime/runtime。
# core-js
core-js 是一个 JavaScript 标准库,里面包含了 ESCAScreipt 2020 在内的多项特性的 polyfill。其作用主要有以下几点
在 core-js3 出来之前,最常用的版本是 core-js@2,但是 core-js@2 的一个最大问题就是包的体积太大(大约有2M),因为其有很多被重复引用的文件。
# core-js@3的重要改变
为了解决上述 core-js2 的问题,core-js@3 使用 Monorepo 进行拆包,拆成了 5 个相关的包,分别如下:
- core-js:是整个
core-js的核心,提供了基础的垫片能力,但是直接使用core-js会污染全局命名空间和对象原型; - core-js-pure:
core-js-pure提供了独立的命名空间,不污染全局变量; - core-js-compact:根据
Browserslist维护了不同宿主环境、不同版本下对应需要支持特性的集合; - core-js-builder:结合
core-js-compact以及core-js,并利用webpack能力,根据需求打包出core-js - core-js-bundle
对于 ECMAScript 中已经稳定的功能,core-js 已经几乎完全支持,并在 core-js@3 中引入了一些新的功能
- 对于一些已经加入到
ES2016-ES2019中的提案,现在已经被标记为稳定功能; - 增加了
proposals配置项,对处在提案阶段的 api 提供支持,但是因为提案阶段并不稳定,在正式加入标准之前,可能会有大的改动,需要谨慎使用;对于一些改变巨大的提案,也进行了对应的更新; - 增加了对一些 web 标准的支持,比如 URL 和
URLSearchParams; - 删除了一些过时的特性;
但是 babel/polyfill 并没有提供从 core-js@2 到 core-js@3 的平滑升级,所以 当 core-js 升级到3.0的版本后,安装 babel@2 的 @babel/polyfill 将被弃用。
在 babel7.4.0 之前,我们可以直接安装 @babel/polyfill 来转换 API,但是在 7.4.0 之后的 Babel 版本,就会提示让我们分开引入 core-js/stable(默认安装3.x)和 regenerator-runtime/runtime
warning @babel/polyfill@7.4.4: � As of Babel 7.4.0, this
package has been deprecated in favor of directly
including core-js/stable (to polyfill ECMAScript
features) and regenerator-runtime/runtime
(needed to use transpiled generator functions):
> import "core-js/stable";
> import "regenerator-runtime/runtime";
# 使用姿势
根据上述的介绍,我们已经知道了,
